/*
 *  arrayMap.h
 *  kangmodb
 *
 *  Created by 강모 김 on 11. 5. 8..
 *  Copyright 2011 강모소프트. All rights reserved.
 *
 */

#include "kdInfra.h"

/** @brief An array map that provides quick access to the mapped element at O(1). Adding an item can take at most O(N).
* This module is used for mappings from stgTableId to stgTable*. To provide the best performance for opening a cursor, mapping from stgTableId to stgTable* is finished at O(1).  
*/
template<class keyT, class valueT>
class kdArrayMap
{
private :
	valueT * map_;
	keyT maxMapSize_;
public :
	kdArrayMap() {}
	~kdArrayMap() {}
	KD_VOID initialize(keyT maxArraySize)
	{
		KD_TRY
		{
			map_ = new valueT[maxArraySize+1];
			if ( map_ == NULL ) {
				KD_THROW( KD_EXCP_NO_MEM );
			}
			memset(map_, 0, sizeof(valueT)*(maxArraySize+1));
			maxMapSize_ = maxArraySize;
		}
		KD_CATCH
		KD_FINALLY
		KD_END
	}
	KD_VOID destroy()
	{
		KD_TRY
		{
			KD_ASSERT( map_ != NULL );
			delete[] map_;
			map_ = NULL;
		}
		KD_CATCH
		KD_FINALLY
		KD_END
	}
	/** @brief Put the value, output the key mapped on the value. Note that "put" interface takes O(N).
	 */
	KD_VOID put(keyT key, valueT value)
	{
		// TODO : concurrency control
		KD_TRY
		{
			KD_ASSERT( map_[key] == (valueT)0 );
			map_[key] = value;
		}
		KD_CATCH
		KD_FINALLY
		KD_END
	}

	/** @brief Put the value, output the key mapped on the value. Note that "put" interface takes O(N).
	 */
	KD_VOID put(valueT value, keyT * key)
	{
		// TODO : concurrency control
		KD_TRY
		{
			// Don't use index 0. 
			for (keyT i=1; i<=maxMapSize_; i++)
			{
				if (map_[i] == (valueT)0)
				{
					*key = i;
					map_[i] = value;
					KD_RETURN;
				}
			}
			KD_THROW(KD_EXCP_ARRAY_MAP_FULL);
		}
		KD_CATCH
		KD_FINALLY
		KD_END
	}

	/** @brief Get the value mapped with the given key 
	 */
	KD_VOID get(keyT key, valueT * value)
	{
		// TODO : concurrency control
		KD_TRY
		{
			KD_ASSERT( key <= maxMapSize_ );
			*value = map_[ key ];
		}
		KD_CATCH
		KD_FINALLY
		KD_END
	}

	/** @brief Remove the key and mapped value 
	*/
	KD_VOID remove(keyT key)
	{
		// TODO : concurrency control
		KD_TRY
		{
			KD_ASSERT( key <= maxMapSize_ );
			map_[ key ] = (valueT) 0;
		}
		KD_CATCH
		KD_FINALLY
		KD_END
	}
};